package jeconbond.economic.market.strategy;

import java.security.InvalidParameterException;
import java.util.HashMap;
import java.util.Map;

import jeconbond.economic.agent.service.IPreActServiceAgent;
import jeconbond.economic.resources.IResourceType;
import jeconbond.economic.resources.ResourceUtils;
import jeconbond.economic.systems.market.IMarketResourceRedestributionSystem;

public class ConcurrentBasedPerformPriceStrategy implements IPerformPriceStrategy {
	private IPerformPriceStrategy substrategy;
	private double concurrentPricePercent;
	private Map<IResourceType, double[]> concurrentPrices;

	public ConcurrentBasedPerformPriceStrategy(
			IPerformPriceStrategy substrategy,
			double concurrentPricePercent,
			Map<IResourceType, double[]> concurrentPrices
	) {
		this.substrategy = substrategy;
		this.concurrentPricePercent = concurrentPricePercent;
		this.concurrentPrices = concurrentPrices;
		if (
				concurrentPricePercent <= 0.0 || 
				concurrentPricePercent > 1.0 || 
				Double.isNaN(concurrentPricePercent)
		) {
			throw new InvalidParameterException("Bad concurrentPricePercent");
		}
	}

	@Override
	public double performPrice(IResourceType resourceType) {
		double subprice = substrategy.performPrice(resourceType);
		double concurrentPrice = getConcurrentPrice(resourceType);
		double price = subprice;
		if (concurrentPrice > subprice) {
			price = concurrentPrice * concurrentPricePercent + (1.0 - concurrentPricePercent) * subprice;
		}
		return price;
	}
	
	private double getConcurrentPrice(IResourceType type) {
		double[] price_ptr = concurrentPrices.get(type);
		if (price_ptr == null) {
			return -1.0;
		}
		return price_ptr[0];
	}
	
	public static class AvaluateMarketPriceAgent implements IPreActServiceAgent {
		private IResourceType[] resources;
		private IMarketResourceRedestributionSystem mrrs;
		private Map<IResourceType, double[]> concurrentPrices = new HashMap<IResourceType, double[]>();

		public AvaluateMarketPriceAgent(
				IResourceType[] resources,
				IMarketResourceRedestributionSystem mrrs
		) {
			this.resources = resources;
			this.mrrs = mrrs;
		}

		public Map<IResourceType, double[]> getConcurrentPrices() {
			return concurrentPrices;
		}

		@Override
		public void processPreProduceStage() {
			for (IResourceType rt : resources) {
				double concurrentPrice = ResourceUtils.avaluateMarketPrice(rt, mrrs);
				if (Double.isNaN(concurrentPrice)) {
					continue;
				}
				double[] storedConcPrice = concurrentPrices.get(rt);
				if (storedConcPrice == null) {
					storedConcPrice = new double[] { concurrentPrice };
					concurrentPrices.put(rt, storedConcPrice);
				}
				storedConcPrice[0] = (storedConcPrice[0] + concurrentPrice) / 2.0;
			}
		}
		@Override
		public void processProduceStage() {}
		@Override
		public void processPostProduceStage() {}
	}
}
